home *** CD-ROM | disk | FTP | other *** search
Wrap
/* Copyright (c) 1995-1999 NEC USA, Inc. All rights reserved. */ /* */ /* The redistribution, use and modification in source or binary forms of */ /* this software is subject to the conditions set forth in the copyright */ /* document ("Copyright") included with this distribution. */ /* * $Id: daemon.c,v 1.62.2.1.2.16 1999/03/05 21:52:47 steve Exp $ */ /* This file has the main function in it for socks5, as well as variables */ /* which most or several modules will use... */ #include "socks5p.h" #include "threads.h" #include "daemon.h" #include "socket.h" #include "protocol.h" #include "msgids.h" #include "log.h" #ifndef _DECTHREADS_ #define MAXTHREADS 64 #else #define MAXTHREADS 16 #endif #ifndef NUMCLIENTS #define NUMCLIENTS 64 #endif #ifndef HAVE_SETSID #ifdef HAVE_SETPGID #define setsid() setpgid(0, getpid()) #elif defined(SETPGRP_VOID) #define setsid() setpgrp() #else #define setsid() setpgrp(0, getpid()) #endif #endif MUTEX_T lt_mutex = MUTEX_INITIALIZER; /* localtime mutex */ MUTEX_T accept_mutex = MUTEX_INITIALIZER; /* localtime mutex */ MUTEX_T conn_mutex = MUTEX_INITIALIZER; /* connection mutex */ MUTEX_T env_mutex = MUTEX_INITIALIZER; /* *env mutex */ MUTEX_T gpw_mutex = MUTEX_INITIALIZER; /* getpwd* mutex */ MUTEX_T gh_mutex = MUTEX_INITIALIZER; /* gethost* mutex */ MUTEX_T gs_mutex = MUTEX_INITIALIZER; /* getserv* mutex */ int nthreads = 0; int nservers = 0; int isthreaded = 0; int servermode = 0; int idletimeout = 15; char *bindif = NULL; u_short ludpport = 0; u_short hudpport = 0xffff; static void version(void) { fprintf(stdout, "Socks5 version: %s\n", SOCKS5_VERSION_NAME); exit(0); } static void usage(void) { fprintf(stderr, "Usage incorrect...\n"); fprintf(stderr, "usage: socks5 "); fprintf(stderr, "[-d [X]|--debug [X]] "); fprintf(stderr, "[-s|--stderr] "); fprintf(stderr, "[-v|--version] "); fprintf(stderr, "\n"); fprintf(stderr, "[-b X|--bindintfc X] "); fprintf(stderr, "[-f|--foreground] "); fprintf(stderr, "[-i|--inetd] "); fprintf(stderr, "[-p|--prefork] "); fprintf(stderr, "[-o|--oneshot] "); fprintf(stderr, "[-t|--threaded] "); fprintf(stderr, "[-n X|--nchildren X]"); fprintf(stderr, "\n"); exit(-1); } int main(int argc, char **argv, char **envp) { char tbuf[1024]; int how = S5_LOG_SYSTEM, level = S5_LOG_INFO; time_t now = time(NULL); int separate = 1; IFTHREADED(MUTEX_SETUP(accept_mutex);) IFTHREADED(MUTEX_SETUP(env_mutex);) IFTHREADED(MUTEX_SETUP(gpw_mutex);) IFTHREADED(MUTEX_SETUP(gh_mutex);) IFTHREADED(MUTEX_SETUP(gs_mutex);) IFTHREADED(MUTEX_SETUP(lt_mutex);) for (argc--, argv++; argc > 0; argc--, argv++) { if (!strncmp(*argv, "-d", strlen("-d")) || !strncmp(*argv, "--debug", strlen("--debug"))) { if (*(argv+1) && isdigit((int)**(argv+1))) { level = S5_LOG_DEBUG(atoi(*++argv)); argc--; } else level = S5_LOG_DEBUG(25); } else if (!strcmp(*argv, "-s") || !strcmp(*argv, "--stderr")) { how = S5_LOG_LOCAL; } else if (!strcmp(*argv, "-i") || !strcmp(*argv, "--inetd")) { servermode = INETD; } else if (!strcmp(*argv, "-f") || !strcmp(*argv, "--foreground")) { separate = 0; } else if (!strcmp(*argv, "-p") || !strcmp(*argv, "--prefork")) { servermode = PREFORKING; } else if (!strcmp(*argv, "-n") || !strcmp(*argv, "--nchildren")) { if (!(*++argv) || !isdigit((unsigned char)**argv)) usage(); else { nservers = atoi(*argv); argc--; } } else if (!strcmp(*argv, "-b") || !strcmp(*argv, "--bindintfc")) { if (!(*++argv)) usage(); else { bindif = strdup(*argv); argc--; } } else if (!strcmp(*argv, "-v") || !strcmp(*argv, "--version")) { version(); } else if (!strcmp(*argv, "-t") || !strcmp(*argv, "--threaded")) { S5LogShowThreadIDS = 1; servermode = THREADED; } else if (!strcmp(*argv, "-o") || !strcmp(*argv, "--oneshot")) { servermode = SINGLESHOT; level = S5_LOG_DEBUG_MAX; how = S5_LOG_LOCAL; separate = 0; } else { usage(); } } if (separate && fork() > 0) exit(0); chdir("/"); umask(0); setsid(); nthreads = MIN(MAXOPENS/4 - 1, MAXTHREADS) - 1; if (nservers == 0) { if (servermode == THREADED) nservers = NUMCLIENTS/4; else nservers = MIN(MAXCLIENTS, NUMCLIENTS); } #ifdef RLIMIT_NOFILE if (servermode == THREADED) { struct rlimit rl; /* try allow for maxc open file descriptors */ if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { if (rl.rlim_cur < rl.rlim_max) { rl.rlim_cur = rl.rlim_max; #ifndef bsdi setrlimit(RLIMIT_NOFILE, &rl); #endif } nthreads = MIN(rl.rlim_cur/4 - 1, MAXTHREADS) - 1; } } #endif #ifdef RLIMIT_NPROC if (servermode != INETD) { struct rlimit rl; /* try allow for maxc children (or MAXCLIENTS) */ if (getrlimit(RLIMIT_NPROC, &rl) == 0 && nservers > rl.rlim_cur && nservers <= rl.rlim_max) { rl.rlim_cur = nservers; setrlimit(RLIMIT_NPROC, &rl); } } #endif S5LogStart(&S5LogDefaultHandle, how, level, "Socks5"); /* make sure that number of child processes will not exceed the system */ /* limit... */ if (nservers > MAXCLIENTS) { S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_START, "Requested child process number (%d). Socks5 will use the system limit (%d)", nservers, MAXCLIENTS); nservers = MAXCLIENTS; } LIBPREFIX2(init)("Socks5"); MUTEX_LOCK(lt_mutex); strftime(tbuf, sizeof(tbuf), "%c", localtime(&now)); MUTEX_UNLOCK(lt_mutex); switch (servermode) { case NORMAL: strcat(tbuf, " in normal mode"); break; case INETD: strcat(tbuf, " from inetd"); break; case PREFORKING: strcat(tbuf, " in preforking mode"); break; case SINGLESHOT: strcat(tbuf, " in single shot mode"); break; case THREADED: strcat(tbuf, " in threading mode"); break; default: strcat(tbuf, " in unknown mode"); break; } S5LogUpdate(S5LogDefaultHandle, S5_LOG_INFO, MSGID_SERVER_START, "Socks5 starting at %s", tbuf); GetConnection(); return(-1); }